package com.qkl.xiatang.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qkl.xiatang.app.entity.feed.AllocAbnDetailEntity;
import com.qkl.xiatang.app.entity.feed.AllocCheckAbnEntity;
import com.qkl.xiatang.app.entity.feed.FeedAllocCheckEntity;
import com.qkl.xiatang.app.mapper.AllocAbnDetailMapper;
import com.qkl.xiatang.app.mapper.AllocCheckAbnMapper;
import com.qkl.xiatang.app.utils.AppUtils;
import com.qkl.xiatang.app.utils.appenum.FeedAllocSerialEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;

/**
 * 喂料异常检测
 */
@Service
@Slf4j
public class AllocCheckAbnService {

    @Autowired
    private AllocCheckAbnMapper allocCheckAbnMapper;

    @Autowired
    private AllocAbnDetailMapper allocAbnDetailMapper;

    @Transactional
    public void checkFeedAllocIsAbn(FeedAllocCheckEntity checkEntity) {
        try {
            String pondId = checkEntity.getPondId();
            int feedStatus = checkEntity.getFeedStatus();

            // 查询最新的异常记录
            QueryWrapper<AllocCheckAbnEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pond_id", pondId)
                    .in("abnormal_type", 0, 1)
                    .orderByDesc("update_time")
                    .last("limit 0,1");
            AllocCheckAbnEntity checkAbn = allocCheckAbnMapper.selectOne(queryWrapper);


            if (null != checkAbn) {
                if (2 == feedStatus) {
                    // 处理第二次异常
                    updateAbnormalRecord(checkAbn, checkEntity, 0);
                } else {
                    // 判断是否恢复正常状态
                    handleAbnormalRecovery(checkAbn, checkEntity);
                }
            } else {
                // 不存在异常记录，处理料多情况
                if (2 == feedStatus) {
                    addAbnormalRecord(checkEntity); // 添加异常记录
                }
            }
        } catch (Exception e) {
            log.error("检查异常出错,请检查!", e);
        }
    }

    // 更新异常记录
    private void updateAbnormalRecord(AllocCheckAbnEntity checkAbn, FeedAllocCheckEntity checkEntity, int abnormalType) {
        checkAbn.setAbnormalType(abnormalType);
        //只有在 abnormalType 为 0 时才重新设置异常时间
        if (abnormalType == 0) {
            checkAbn.setAbnormalTime(checkEntity.getAllocDate());
            checkAbn.setSerialNo(checkEntity.getSerialNo());
        }
        checkAbn.setUpdateBy(checkEntity.getUserId());
        checkAbn.setUpdateTime(new Date());
        allocCheckAbnMapper.updateById(checkAbn);

        AllocAbnDetailEntity allocAbnDetailEntity = createAllocAbnDetail(checkAbn, checkEntity, abnormalType);

        //只有当条是异常时， 我才会重新设置异常原因
        if (abnormalType == 0) {
            allocAbnDetailEntity.setAbnormalCause("料多");
        }

        //只有恢复异常时， 才会设置恢复原因
        if (abnormalType == 2) {
            allocAbnDetailEntity.setAbnormalRecovery(0);
        }

        allocAbnDetailMapper.insert(allocAbnDetailEntity);
    }

    // 处理异常恢复逻辑
    private void handleAbnormalRecovery(AllocCheckAbnEntity checkAbn, FeedAllocCheckEntity checkEntity) {
        Date abnormalTime = checkAbn.getAbnormalTime();
        int serialNo = checkAbn.getSerialNo();
        LocalDate localTargetDate = abnormalTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        Date instant = Date.from(localTargetDate.plusDays(3).atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date allocDate = checkEntity.getAllocDate();

        if (allocDate.compareTo(instant) >= 0 || (allocDate.compareTo(instant) == 0 && checkEntity.getSerialNo() == serialNo)) {
            // 异常恢复
            updateAbnormalRecord(checkAbn, checkEntity, 2);
        } else {
            // 在恢复异常中
            updateAbnormalRecord(checkAbn, checkEntity, 1);
        }
    }

    // 添加异常记录
    private void addAbnormalRecord(FeedAllocCheckEntity checkEntity) {
        AllocCheckAbnEntity allocCheckAbnEntity = new AllocCheckAbnEntity();
        allocCheckAbnEntity.setId(AppUtils.genIdStr(allocCheckAbnEntity));
        allocCheckAbnEntity.setCompanyId(checkEntity.getCompanyId());
        allocCheckAbnEntity.setPondId(checkEntity.getPondId());
        allocCheckAbnEntity.setAbnormalType(0);
        allocCheckAbnEntity.setAbnormalTime(checkEntity.getAllocDate());
        allocCheckAbnEntity.setSerialNo(checkEntity.getSerialNo());
        allocCheckAbnEntity.setCreateBy(checkEntity.getUserId());
        allocCheckAbnEntity.setCreateTime(new Date());
        allocCheckAbnEntity.setUpdateBy(checkEntity.getUserId());
        allocCheckAbnEntity.setUpdateTime(new Date());
        allocCheckAbnMapper.insert(allocCheckAbnEntity);

        AllocAbnDetailEntity allocAbnDetailEntity = createAllocAbnDetail(allocCheckAbnEntity, checkEntity, 0);
        allocAbnDetailEntity.setAbnormalCause("料多");  // 设置异常原因
        allocAbnDetailMapper.insert(allocAbnDetailEntity);
    }

    // 创建AllocAbnDetailEntity对象
    private AllocAbnDetailEntity createAllocAbnDetail(AllocCheckAbnEntity checkAbn, FeedAllocCheckEntity checkEntity, int abnormalType) {
        AllocAbnDetailEntity allocAbnDetailEntity = new AllocAbnDetailEntity();
        allocAbnDetailEntity.setId(AppUtils.genIdStr(allocAbnDetailEntity));
        allocAbnDetailEntity.setAllocAbnId(checkAbn.getId());
        allocAbnDetailEntity.setCheckId(checkEntity.getId());
        allocAbnDetailEntity.setAllocDate(checkEntity.getAllocDate());
        allocAbnDetailEntity.setSerialNo(checkEntity.getSerialNo());
        allocAbnDetailEntity.setSerialName(FeedAllocSerialEnum.getNameByNo(checkEntity.getSerialNo()));
        allocAbnDetailEntity.setShrimpStatus(checkEntity.getShrimpStatus());
        allocAbnDetailEntity.setFeedStatus(checkEntity.getFeedStatus());
        allocAbnDetailEntity.setStatusName(checkEntity.getStatusName());
        allocAbnDetailEntity.setAbnormalType(abnormalType);
        allocAbnDetailEntity.setCreateBy(checkEntity.getUserId());
        allocAbnDetailEntity.setCreateTime(new Date());
        return allocAbnDetailEntity;
    }
}
